
const commandLineArgs = require('command-line-args')

const commandLineUsage = require('command-line-usage')


const chalk = require('chalk')
const fs = require('fs')
const optionDefinitions = [
  {
    name: 'help',
    description: '帮助',
    alias: 'h',
    type: Boolean
  },
  { name: 'serverMode', alias: 'S', type: Boolean,description:  '服务器模式,可忽略'},
  { name: 'start', alias: 's', type: Boolean,description:  '启动'},
  // { name: 'help', alias: '?', type: String },
   { name: 'host', alias: 'H', type: String,description: '监听主机,默认是0.0.0.0'},
   { name: 'port', alias: 'p', type: String ,  description: '端口,默认3000'},
   { name: 'token', alias: 't', type: String ,  description: 'websocket管理端/广播端的token,默认是admin'},
   { name: 'root', alias: 'r', type: String,description:"http文件目录,默认是public目录,http访问路径是/p/" },
 
  // { name: 'port', type: String, multiple: true, defaultOption: true },
  // { name: 'timeout', alias: 't', type: Number }
 ]
const usage = commandLineUsage([
  {
    header: 'Websocket Server',
    content: chalk.green(`启动uniapp热更新的websocket服务器和http服务器,
1. websocket服务器/ws/uniapp/,http服务器前缀是/p/,存放热更新的文件
2. app连接地址是ip:端口/ws/uniapp/自定义字母
3. 需要热更新的客户端/管理端连接 /ws/uniapp/自定义?token=admin 
4. 静态文件路径/public目录
`)
  },
  {
    header: 'Options',
    optionList: optionDefinitions
  },
  {
    content: ''
  }
])


const options = commandLineArgs(optionDefinitions)

var os=require("os");

console.log('getopts',options)

var networkInterfaces=os.networkInterfaces();

const config={
  host:options['host'] || process.env.WS_DEBUG_HOST || '0.0.0.0',
  port:options['port'] || process.env.WS_DEBUG_PORT || '3000',
  public:options['root'] || process.env.WS_DEBUG_ROOT || 'public',
  adminToken:'admin',
}

const isShowHelp=options.help || (Object.keys(options).length<1) 

if(isShowHelp) {
  console.log(usage)
  process.exit()
}
const fastify = require('fastify')({ logger: true })

const path = require('path');
const { mkdirSync } = require('fs')

// const serveStatic = require('serve-static');
 
// fastify.use('/', serveStatic(path.resolve(__dirname, 'public')));
 
const publicPath=path.isAbsolute(config.public)?config.public:path.join(__dirname, config.public)
if(!fs.existsSync(publicPath)){
  mkdirSync(publicPath)
}
fastify.register(require('fastify-static'), {
  root: publicPath,
  prefix: '/p/', // optional: default '/'
})


// fastify.get('/b', function (req, reply) {
//   return reply.sendFile('myHtml.html', path.join(__dirname, 'build')) // serving a file from a different root location
// })

// fastify.get('/another/path', function (req, reply) {
//   return reply.sendFile('myHtml.html', { cacheControl: false }) // overriding the options disabling cache-control headers
// })



fastify.register(require('fastify-websocket'))

// Declare a route
fastify.get('/f', async (request, reply) => {
  return { hello: 'world' }
})

let conns={}
fastify.get('/ws/uniapp/*', { websocket: true }, (connection /* SocketStream */, req /* FastifyRequest */) => {
  console.log("connection",[req.socket.remoteAddress,req.headers])
  conns[req.url]=connection
  connection.socket.on('message', message => {
    const msg=message.toString()
    console.log('client msg',msg)
    if(isAdmin){
      console.log('broadcast msg',msg)
      Object.keys(conns).forEach(key=>{

        if(key!=req.url){
          conns[key].socket.send(msg)
        } else {
          console.log("source conn",req.url)
        }
        
      })
    } 
    
  })
})
function isAdmin(req){
    return req.query && req.query.token==config.adminToken
}

const start = async () => {
    try {
      await fastify.listen(config.port,config.host)
      
    } catch (err) {
      fastify.log.error(err)
      process.exit(1)
    }
  }
  let hosts=[]
  Object.values(networkInterfaces).forEach(inter=>{
    inter.forEach(i=>{
      if(/^([\d]{1,3}\.){3}\d{1,3}$/.test(i['address'])){
        hosts.push(i['address'])
      }
    })
  })
if(config.host=='0.0.0.0')  {
  hostStr=hosts.map(host=>{
    return `websocket服务器: ws://${host}:${config.port}/ws/uniapp/自定义id
http服务器 http://${host}:${config.port}/p`  
  }).join("\n\n")

} else {
  hostStr=`ws://${config.host}:${config.port}/ws/uniapp/自定义id
  http服务器 http://${config.host}:${config.port}/p`
}
let adminStr=`
管理端在ws连接地址后加?token=管理token
`
if(options.start) {
    server=`
${hostStr}
${adminStr}
`   
    console.log(chalk.green(server))
    start()
  }
